﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the G.O.S.E(Game Online Server Engine) for .NET.
//
//                 2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using Demo_G.O.S.E.ServerEngine.Map;
using Demo_G.O.S.E.ServerEngine.Util;
using Demo_G.O.S.E.ServerEngine.Item;
using Demo_G.O.S.E.ServerEngine.Timer;
using Demo_G.O.S.E.ServerEngine.Server;
using Demo_G.O.S.E.ServerEngine.Common;
using Demo_G.O.S.E.ServerEngine.Network;
using Demo_G.O.S.E.ServerEngine.MobileAI;
using Demo_G.O.S.E.ServerEngine.Creature;
using Demo_G.O.S.E.ServerEngine.ThreadPool;
using Demo_G.O.S.E.ServerEngine.Character;
#endregion

namespace Demo_G.O.S.E.ServerEngine.World
{
    /// <summary>
    /// BaseWorld 是管理整个游戏世界的入口
    /// </summary>
    [MultiThreadedSupportgAttribute( "当前的类所有成员都可锁定,支持多线程操作" )]
    public class BaseWorld
    {
        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 
        /// </summary>
        public BaseWorld()
        {
            m_WaitExecute.SetBaseWorld( this ); // 初始化BaseWorld
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 是否正在存储数据中...
        /// </summary>
        private bool m_Saving = false;
        #endregion
        /// <summary>
        /// 是否正在存储数据中...
        /// </summary>
        public bool Saving
        {
            get { return m_Saving; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 数据存储的时间间隔
        /// </summary>
        private TimeSpan m_SaveTimeSpan = TimeSpan.FromMinutes( 5.0 );
        #endregion
        /// <summary>
        /// 存储数据的时间间隔
        /// </summary>
        public TimeSpan IntervalSave
        {
            get { return m_SaveTimeSpan; }
            set
            {
                if ( m_SaveTimeSpan.Ticks != value.Ticks )
                {
                    m_SaveTimeSpan = value;
                    StartSaveTimeSlice();
                }
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 游戏世界的名字
        /// </summary>
        private string m_strWorldName = string.Empty;
        #endregion
        /// <summary>
        /// 游戏世界的名字
        /// </summary>
        public string WorldName
        {
            get { return m_strWorldName; }
            set { m_strWorldName = value; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private WorldWaitExecute m_WaitExecute = new WorldWaitExecute();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public WorldWaitExecute WaitExecute
        {
            get { return m_WaitExecute; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private BaseMapManager m_BaseMapManage = new BaseMapManager();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public BaseMapManager MapManager
        {
            get { return m_BaseMapManage; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private NetStateManager m_NetStateManage = new NetStateManager();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public NetStateManager NetStateManager
        {
            get { return m_NetStateManage; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private BaseItemManager m_BaseItemManage = new BaseItemManager();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public BaseItemManager ItemManager
        {
            get { return m_BaseItemManage; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private BaseItemTemplateManager m_BaseItemTemplateManage = new BaseItemTemplateManager();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public BaseItemTemplateManager ItemTemplateManager
        {
            get { return m_BaseItemTemplateManage; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private BaseCreatureManager m_BaseCreatureManage = new BaseCreatureManager();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public BaseCreatureManager CreatureManager
        {
            get { return m_BaseCreatureManage; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private BaseCreatureTemplateManager m_BaseCreatureTemplateManage = new BaseCreatureTemplateManager();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public BaseCreatureTemplateManager CreatureTemplateManager
        {
            get { return m_BaseCreatureTemplateManage; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private BaseCharacterManager m_BaseCharacterManage = new BaseCharacterManager();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public BaseCharacterManager CharacterManager
        {
            get { return m_BaseCharacterManage; }
        }

        #region zh-CHS MessagePump 属性 | en MessagePump Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 多个监听的端口
        /// </summary>
        private MessagePump[] m_MessagePump = new MessagePump[0];
        #endregion
        /// <summary>
        /// 监听的端口
        /// </summary>
        public MessagePump[] MessagePump
        {
            get { return m_MessagePump; }
        }

        #region zh-CHS MessagePump 方法 | en MessagePump Method
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 只锁定添加操作(因为是数组，其它的地方就可以不用锁定的)
        /// </summary>
        private ReaderWriterLockSlim m_LockAddMessagePump = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 添加监听的端口
        /// </summary>
        /// <param name="messagePump"></param>
        public void AddMessagePump( MessagePump messagePump )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockAddMessagePump );
            {
                // 创建新的MessagePump数组,添加数据,交换数组数据,不需要锁定,没有引用时自动会回收数据
                MessagePump[] tempMessagePump = new MessagePump[m_MessagePump.Length + 1];

                for ( int iIndex = 0; iIndex < m_MessagePump.Length; ++iIndex )
                    tempMessagePump[iIndex] = m_MessagePump[iIndex];

                tempMessagePump[m_MessagePump.Length] = messagePump;
                messagePump.SetBaseWorld( this );

                m_MessagePump = tempMessagePump;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockAddMessagePump );
        }
        #endregion

        #endregion

        #endregion

        #region zh-CHS 内部方法 | en Internal Method

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 数据保存的时间片
        /// </summary>
        private TimeSlice m_SaveTimeSlice = null;
        #endregion
        /// <summary>
        /// 开始运行数据保存的时间片
        /// </summary>
        internal void StartSaveTimeSlice()
        {
            if ( m_SaveTimeSlice != null )
                m_SaveTimeSlice.IntervalTime = m_SaveTimeSpan; // 如果存在了就只改变间隔时间
            else
                // 启动BaseWorld保存数据的时间片
                m_SaveTimeSlice = TimeSlice.StartTimeSlice( m_SaveTimeSpan, m_SaveTimeSpan, new TimeSliceCallback( OnSave ) );
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private CallbackThreadPool m_ThreadPool = null;
        /// <summary>
        /// 
        /// </summary>
        private BaseWorldEventArgs m_BaseWorldEventArgs = null;
        /// <summary>
        /// 可处理信号的数量
        /// </summary>
        private long m_MaxSignalCount = 0;
        #endregion
        /// <summary>
        /// 开始线程池
        /// </summary>
        internal void StartThreadPool( int maxThreadsAllowed )
        {
            if ( m_BaseWorldEventArgs == null )
                m_BaseWorldEventArgs = new BaseWorldEventArgs( this ); // 在世界时间片中调用

            if ( m_ThreadPool == null )
            {
                // 最多的可处理信号的数量
                m_MaxSignalCount = maxThreadsAllowed * 3;
                m_ThreadPool = new CallbackThreadPool( CallbackThreadPool.TIMEOUT_INFINITE, maxThreadsAllowed, maxThreadsAllowed );
                m_ThreadPool.ThreadEvent += new EventHandler<CallbackThreadPoolEventArgs>( ThreadPool_ThreadEvent );
            }
            else
                Debug.WriteLine( "BaseWorld.StartThreadPool(...) - m_ThreadPool != null error!" );
        }

        #region zh-CHS 私有的事件处理函数 | en Private Event Handlers
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        private void ThreadPool_ThreadEvent( object sender, CallbackThreadPoolEventArgs eventArgs )
        {
            switch ( eventArgs.Reason )
            {
                case CallbackReason.AddingThreadToPool:

                    break;
                case CallbackReason.RemovingThreadFromPool:
                    
                    break;
                default:

                    break;
            }
        }
        #endregion

        /// <summary>
        /// 停止线程池
        /// </summary>
        internal void StopThreadPool()
        {
            CallbackThreadPool tempThreadPool = m_ThreadPool;
            m_ThreadPool = null;

            if ( tempThreadPool != null )
                tempThreadPool.Dispose();
        }

        /// <summary>
        /// 表示线程池线程要执行的回调方法。
        /// </summary>
        /// <param name="state"></param>
        private void SliceWorld( object state )
        {
            if ( BaseServer.Closing || m_ThreadPool == null )
            {
                Interlocked.Decrement( ref m_SignalCount );
                return;
            }

            // 运行库为每个可执行文件创建一个异常信息表。在异常信息表中，可执行文件的每个方法都有一个关联的异常处理信息数组（可以为空）。
            // 数组中的每一项描述一个受保护的代码块、任何与该代码关联的异常筛选器和任何异常处理程序（Catch 语句）。此异常表非常有效，
            // 在没有发生异常时，在处理器时间或内存使用上没有性能损失。仅在异常发生时使用资源。
            try
            {
                BaseCreature.Slice();
                BaseItem.Slice();

                //AISystem.Slice();
                TimeSlice.Slice();

                // 需要保存一个引用的副本,防止多线程添加的时候调用失败的可能
                // 其实不需要的,数组永远都不会添加和删除
                MessagePump[] tempArray = m_MessagePump;

                // foreach的平均花费时间只有for的30%
                foreach ( MessagePump messagePump in tempArray )
                    messagePump.Slice();

                // 发送缓存的数据
                FlushAll();

                ProcessDisposed();

                EventHandler<BaseWorldEventArgs> tempEventArgs = m_ThreadEventSlice;
                if ( tempEventArgs != null )
                    tempEventArgs( this, m_BaseWorldEventArgs );

                m_WaitExecute.Slice();
            }
            catch ( Exception exception )
            {
                BaseServer.UnhandledException( this, new UnhandledExceptionEventArgs( exception, true ) );
            }
            finally
            {
                Interlocked.Decrement( ref m_SignalCount );
            }
        }

        #region zh-CHS CheckAllAlive(检查客户端状态) 函数 | en CheckAllAlive(NetState) Methods
        /// <summary>
        /// 初始化在线状态的检查
        /// </summary>
        internal void StartCheckAllAliveTime()
        {
            // 检测用户是否超时
            // 创建检测用户是否超时的时间片(默认5分钟)
            TimeSlice.StartTimeSlice( TimerProcessPriority.Lowest, NetState.CheckAliveTime, NetState.CheckAliveTime, new TimeSliceCallback( CheckAllAlive ) );
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 是否在调用CheckAllAlive(...)中...(防止多线程多次调用CheckAllAlive(...)函数)
        /// </summary>
        private bool m_InCheckAllAlive = false;
        /// <summary>
        /// 是否在调用CheckAllAlive(...)中...的锁
        /// </summary>
        private ReaderWriterLockSlim m_LockInCheckAllAlive = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 检查全部的连接是否有效
        /// </summary>
        private void CheckAllAlive()
        {
            bool bIsChange = false;

            // 检查是否已经在处理CheckAllAlive(...)的调用
            if ( ReaderWriterLockSlimEx.TryEnterWriteLock( m_LockInCheckAllAlive ) == false )
                return;
            {
                if ( m_InCheckAllAlive == false ) // 没有锁定
                    bIsChange = m_InCheckAllAlive = true;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockInCheckAllAlive );

            // 已经在处理CheckAllAlive(...)中
            if ( bIsChange == false && m_InCheckAllAlive )
                return;

            // 处理数据
            NetState[] netStateArray = m_NetStateManage.ToArray();
            foreach ( NetState netState in netStateArray )
                netState.CheckAlive();

            // 已经处理完CheckAllAlive(...)的调用
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockInCheckAllAlive );
            {
                m_InCheckAllAlive = false;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockInCheckAllAlive );
        }
        #endregion

        #region zh-CHS FlushAll(发送全部数据) 函数 | en FlushAll(NetState) Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 需要处理发送的客户端的集合
        /// </summary>
        private Queue<NetState> m_NetStateFlush = new Queue<NetState>();
        /// <summary>
        /// 处理发送的客户端的集合锁
        /// </summary>
        private ReaderWriterLockSlim m_LockNetStateFlush = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 放入处理发送的客户端的集合内,等待处理
        /// </summary>
        /// <param name="netSatate"></param>
        internal void FlushNetStates( NetState netSatate )
        {
            if ( netSatate.InFlushQueue() == false )
                return;

            ReaderWriterLockSlimEx.EnterWriteLock(m_LockNetStateFlush);
            {
                m_NetStateFlush.Enqueue( netSatate );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockNetStateFlush );
        }

        /// <summary>
        /// 发送全部的数据
        /// </summary>
        internal void FlushAll()
        {
            // 处理数据
            NetState[] netStateArray = null;

            ReaderWriterLockSlimEx.EnterWriteLock( m_LockNetStateFlush );
            {
                if ( m_NetStateFlush.Count > 0 )
                {
                    netStateArray = m_NetStateFlush.ToArray();
                    m_NetStateFlush.Clear();
                }
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockNetStateFlush );

            if ( netStateArray == null )
                return;

            foreach ( NetState netState in netStateArray )
            {
                if ( netState.Running ) // 如果NetState有效
                {
                    netState.Flush();

                    netState.OutFlushQueue(); // 处理完毕

                    // 如果还有没有全部Flush的数据则添加(再次Flush数据),防止多线程漏处理的问题
                    if ( netState.SendQueue.IsFlushReady )
                        FlushNetStates( netState );
                }
            }
        }
        #endregion

        #region zh-CHS ProcessDisposed(处理断开) 方法 | en ProcessDisposed(NetState) Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 需要处理的无效客户端的集合
        /// </summary>
        private Queue<NetState> m_NetStateDisposed = new Queue<NetState>();
        /// <summary>
        /// 无效客户端的集合锁
        /// </summary>
        private ReaderWriterLockSlim m_LockNetStateDisposed = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 放入无效客户端的集合内,等待处理
        /// </summary>
        /// <param name="netSatate"></param>
        internal void DisposedNetStates( NetState netSatate )
        {
            ReaderWriterLockSlimEx.EnterWriteLock(m_LockNetStateDisposed);
            {
                m_NetStateDisposed.Enqueue( netSatate );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockNetStateDisposed );
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当断开处理的累计数量到该数量时将中断后面的调用
        /// </summary>
        private static int s_BreakCount = 16; // 默认值(在多线程中不因该太多)
        /// <summary>
        /// 是否在调用ProcessDisposed(...)中...(防止多线程多次调用ProcessDisposed(...)函数)
        /// </summary>
        private bool m_InProcessDisposed = false;
        /// <summary>
        /// 是否在调用ProcessDisposed(...)中...的锁
        /// </summary>
        private ReaderWriterLockSlim m_LockInProcessDisposed = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 处理全部的已断开连接的客户,不要处理过多的断开,以影响时间片的处理
        /// 主要是处理NetStateManage内的NetState
        /// </summary>
        internal void ProcessDisposed()
        {
            bool bIsChange = false;

            // 检查是否已经在处理ProcessDisposed(...)的调用
            if ( ReaderWriterLockSlimEx.TryEnterWriteLock( m_LockInProcessDisposed ) == false )
                return;
            {
                if ( m_InProcessDisposed == false ) // 没有锁定
                    bIsChange = m_InProcessDisposed = true;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockInProcessDisposed );

            // 已经在处理ProcessDisposed(...)中
            if ( bIsChange == false && m_InProcessDisposed )
                return;

            do
            {
                // 使用数组减少锁定时间
                NetState[] netStateArray = null;

                if ( ReaderWriterLockSlimEx.TryEnterWriteLock( m_LockNetStateDisposed ) == false )
                    break;
                {
                    if ( m_NetStateDisposed.Count > 0 )
                    {
                        // 断开连接的客户先进先出列队集合的数量(和中断处理比较)
                        long iQueueCountAtNetState = m_NetStateDisposed.Count;
                        if ( iQueueCountAtNetState <= s_BreakCount )
                        {
                            netStateArray = m_NetStateDisposed.ToArray();
                            m_NetStateDisposed.Clear();
                        }
                        else
                        {
                            netStateArray = new NetState[s_BreakCount];
                            for ( long iIndex = 0; iIndex < s_BreakCount; iIndex++ )
                                netStateArray[iIndex] = m_NetStateDisposed.Dequeue();
                        }
                    }
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockNetStateDisposed );

                // 如果没有需要处理的数据则返回
                if ( netStateArray == null )
                    break;

                foreach ( NetState netState in netStateArray )
                {
                    m_NetStateManage.InternalRemoveNetState( netState );
                }
            } while ( false );

            // 已经处理完ProcessDisposed(...)的调用
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockInProcessDisposed );
            {
                m_InProcessDisposed = false;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockInProcessDisposed );
        }
        #endregion

        #endregion

        #region zh-CHS 共有方法 | en Public Method
        /// <summary>
        /// 广播数据信息
        /// </summary>
        /// <param name="state"></param>
        /// <param name="strText"></param>
        public void Broadcast( object state, string strText )
        {
            OnBroadcast( state, strText );
        }

        /// <summary>
        /// 广播数据信息
        /// </summary>
        /// <param name="state"></param>
        /// <param name="strFormat"></param>
        /// <param name="args"></param>
        public void Broadcast( object state, string strFormat, params object[] args )
        {
            Broadcast( state, string.Format( strFormat, args ) );
        }

        /// <summary>
        /// 保存世界的数据
        /// </summary>
        public void Save()
        {
            // 保存世界的数据必须要成功才返回
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockSave );
            {
                // 保存数据中......
                m_Saving = true;

                LOGs.WriteLine( LogMessageType.MSG_NOTICE, "游戏世界: 开始保存游戏世界数据中......" );

                // 保存数据
                EventHandler<BaseWorldEventArgs> tempEvent = m_ThreadEventSaveWorld;
                if ( tempEvent != null )
                {
                    BaseWorldEventArgs worldEventArgs = new BaseWorldEventArgs( this );
                    tempEvent( this, worldEventArgs );
                }

                LOGs.WriteLine( LogMessageType.MSG_NOTICE, "游戏世界: 游戏世界数据保存调用完毕." );

                // 保存数据结束......
                m_Saving = false;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockSave );
        }
        #endregion

        #region zh-CHS 方法覆盖 | en Override Methods
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return m_strWorldName;
        }
        #endregion

        #region zh-CHS 共有通知信号方法 | en Public WorldSignal Method
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private long m_SignalCount = 0;
        /// <summary>
        /// 
        /// </summary>
        private object m_LockSignalCount = new object();
        #endregion
        /// <summary>
        /// 游戏世界的通知信号
        /// </summary>
        public void SetWorldSignal()
        {
            if ( m_SignalCount > m_MaxSignalCount )
                return;
            else
                Interlocked.Increment( ref m_SignalCount );

            // 打开默认线程池的处理
            CallbackThreadPool tempThreadPool = m_ThreadPool;
            {
                if ( tempThreadPool != null )
                    tempThreadPool.QueueUserWorkItem( SliceWorld );
            }
        }
        #endregion

        #region zh-CHS 内部的事件处理函数 | en Internal Event Handlers
        /// <summary>
        /// 初始化世界服务
        /// </summary>
        internal void OnInitOnce()
        {
            // 在开始运行世界之前,初始化一次BaseWorld
            // 需要一个副本是因为可能在需要调用的时候,已经注销掉了
            EventHandler<BaseWorldEventArgs> tempEvent = m_ThreadEventInitOnceWorld;
            if ( tempEvent != null )
            {
                BaseWorldEventArgs worldEventArgs = new BaseWorldEventArgs( this );
                tempEvent( this, worldEventArgs );
            }
        }

        /// <summary>
        /// 结束世界服务
        /// </summary>
        internal void OnExit()
        {
            // 在结束世界之前,调用一次
            EventHandler<BaseWorldEventArgs> tempEvent = m_ThreadEventExitWorld;
            if ( tempEvent != null )
            {
                BaseWorldEventArgs worldEventArgs = new BaseWorldEventArgs( this );
                tempEvent( this, worldEventArgs );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockSave = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 保存世界服务
        /// </summary>
        internal void OnSave()
        {
            if ( ReaderWriterLockSlimEx.TryEnterWriteLock( m_LockSave ) == false )
            {
                LOGs.WriteLine( LogMessageType.MSG_NOTICE, "游戏世界: 游戏世界数据正在保存中,请稍候再试......" );
                return;
            }
            else
            {
                // 保存数据
                EventHandler<BaseWorldEventArgs> tempEvent = m_ThreadEventSaveWorld;
                if ( tempEvent != null )
                {
                    // 保存数据中......
                    m_Saving = true;

                    LOGs.WriteLine( LogMessageType.MSG_NOTICE, "游戏世界: 开始保存游戏世界数据中......" );

                    BaseWorldEventArgs worldEventArgs = new BaseWorldEventArgs( this );
                    tempEvent( this, worldEventArgs );

                    LOGs.WriteLine( LogMessageType.MSG_NOTICE, "游戏世界: 游戏世界数据保存调用完毕." );

                    // 保存数据结束......
                    m_Saving = false;
                }
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockSave );
        }

        /// <summary>
        /// 广播数据到整个世界服务
        /// </summary>
        /// <param name="state"></param>
        /// <param name="strText"></param>
        internal void OnBroadcast( object state, string strText )
        {
            // 广播数据
            EventHandler<BaseWorldEventArgs> tempEvent = m_ThreadEventBroadcast;
            if ( tempEvent != null )
            {
                BroadcastEventArgs worldEventArgs = new BroadcastEventArgs( this, strText, state );
                tempEvent( this, worldEventArgs );
            }
        }
        #endregion

        #region zh-CHS 共有事件 | en Public Event

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<BaseWorldEventArgs> m_ThreadEventSlice;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventSlice = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// World可处理的时间片
        /// </summary>
        public event EventHandler<BaseWorldEventArgs> ThreadEventSlice
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock(m_LockThreadEventSlice);
                {
                    m_ThreadEventSlice += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventSlice );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventSlice );
                {
                    m_ThreadEventSlice -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventSlice );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<BaseWorldEventArgs> m_ThreadEventInitOnceWorld;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventInitOnceWorld = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<BaseWorldEventArgs> ThreadEventInitOnceWorld
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventInitOnceWorld );
                {
                    m_ThreadEventInitOnceWorld += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventInitOnceWorld );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventInitOnceWorld );
                {
                    m_ThreadEventInitOnceWorld -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventInitOnceWorld );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<BaseWorldEventArgs> m_ThreadEventExitWorld;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventExitWorld = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<BaseWorldEventArgs> ThreadEventExitWorld
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventExitWorld );
                {
                    m_ThreadEventExitWorld += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventExitWorld );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventExitWorld );
                {
                    m_ThreadEventExitWorld -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventExitWorld );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<BaseWorldEventArgs> m_ThreadEventSaveWorld;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventSaveWorld = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<BaseWorldEventArgs> ThreadEventSaveWorld
        {
            add 
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventSaveWorld );
                {
                    m_ThreadEventSaveWorld += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventSaveWorld );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventSaveWorld );
                {
                    m_ThreadEventSaveWorld -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventSaveWorld );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<BaseWorldEventArgs> m_ThreadEventBroadcast;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventBroadcast = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<BaseWorldEventArgs> ThreadEventBroadcast
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventBroadcast );
                {
                    m_ThreadEventBroadcast += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventBroadcast );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventBroadcast );
                {
                    m_ThreadEventBroadcast -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventBroadcast );
            }
        }

        #endregion
    }
}
#endregion